package com.egao.common.module.recommendation.service.impl;


import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.egao.common.component.minio.config.MinioBucket;
import com.egao.common.core.exception.BusinessException;
import com.egao.common.core.exception.ParameterException;
import com.egao.common.core.web.JsonResult;
import com.egao.common.core.web.PageParam;
import com.egao.common.core.web.PageResult;
import com.egao.common.manage.CommonRefService;
import com.egao.common.module.recommendation.constants.RecommendationConstants;
import com.egao.common.module.recommendation.entity.DirectionalApplicationForm;
import com.egao.common.module.recommendation.entity.FreelanceRegistrationForm;
import com.egao.common.module.recommendation.entity.GraduateEmploymentCertification;
import com.egao.common.module.recommendation.entity.vo.*;
import com.egao.common.module.recommendation.mapper.DirectionalApplicationFormMapper;
import com.egao.common.module.recommendation.service.IDirectionalApplicationFormService;
import com.egao.common.module.student.entity.Student;
import com.egao.common.module.student.mapper.StudentMapper;
import com.egao.common.module.system.constants.DictConstants;
import com.egao.common.module.system.constants.UserConstants;
import com.egao.common.module.system.entity.College;
import com.egao.common.module.system.entity.Major;
import com.egao.common.module.system.entity.User;
import com.egao.common.module.system.mapper.CollegeMapper;
import com.egao.common.module.system.mapper.MajorMapper;
import com.egao.common.module.system.mapper.UserMapper;
import com.egao.common.module.system.service.DictService;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.*;
import com.itextpdf.layout.properties.*;
import com.itextpdf.text.Utilities;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

import static com.egao.common.module.recommendation.constants.RecommendationConstants.RECOMMENDATION_STATUS_PASS;
import static com.microsoft.schemas.vml.STExt.Enum.table;


/**
 *  服务实现类
 *
 * @author cj
 */
@Service
public class DirectionalApplicationFormServiceImpl extends ServiceImpl<DirectionalApplicationFormMapper, DirectionalApplicationForm> implements IDirectionalApplicationFormService {

    private StudentMapper studentMapper;
    private UserMapper userMapper;
    private CommonRefService refService;
    private CollegeMapper collegeMapper;
    private MajorMapper majorMapper;
    private DictService dictService;

    @Value("${minio.recmdDir}")
    private String recmdDir;
    @Value("${minio.endpoint}")
    private String endpoint;
    @Value("${pdf.font}")
    private String pdfFont;
    @Value("${pdf.picture}")
    private String pdfPicture;

    @Autowired
    public DirectionalApplicationFormServiceImpl(StudentMapper studentMapper, UserMapper userMapper, CommonRefService refService, CollegeMapper collegeMapper, MajorMapper majorMapper,  DictService dictService) {
        this.studentMapper = studentMapper;
        this.userMapper = userMapper;
        this.refService = refService;
        this.collegeMapper = collegeMapper;
        this.majorMapper = majorMapper;
        this.dictService = dictService;
    }

    @Override
    public PageResult<RecommendationListVo> list(PageParam<DirectionalApplicationForm> page) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        User curUser = (User) authentication.getPrincipal();
        QueryWrapper<DirectionalApplicationForm> wrapper = new QueryWrapper<>();
        wrapper.ge(page.getPageData().get("beginDate") != null, "update_time", page.getPageData().get("beginDate"));
        wrapper.lt(page.getPageData().get("endDate") != null, "update_time", page.getPageData().get("endDate"));
        wrapper.eq(page.getPageData().get("status") != null, "status", page.getPageData().get("status"));
        // 学生只能查看自己的记录
        Student student = studentMapper.selectOne(new QueryWrapper<Student>().eq("user_id", curUser.getUserId()));
        if (student != null) {
            wrapper.eq("user_id", student.getUserId());
            return new PageResult<>(models2vos(this.page(page, wrapper).getRecords()), page.getTotal());
        }
        //教师逻辑，仅查询本院学生
        User teacher = userMapper.selectById(curUser.getUserId());
        wrapper.eq(curUser.getDegreeScope() != null && !UserConstants.DEGREE_SCOPE_ALL.equals(curUser.getDegreeScope()),
                "degree", curUser.getDegreeScope());
        wrapper.eq("college_code", teacher.getCollegeCode());
        wrapper.ne("status", RecommendationConstants.RECOMMENDATION_STATUS_INIT);
        //处理筛选条件
        if (page.getPageData().get("con") != null && StrUtil.isNotBlank((String) page.getPageData().get("con"))) {
            wrapper.and(w -> w.like("xh", page.getPageData().get("con")).or().like("xm", page.getPageData().get("con")));
        }
        return new PageResult<>(models2vos(this.page(page, wrapper).getRecords()), page.getTotal());
    }

    public List<RecommendationListVo> models2vos(List<DirectionalApplicationForm> models) {
        LinkedList<RecommendationListVo> vos = new LinkedList<>();
        List<String> codes = new LinkedList<>();
        models.forEach(model -> {
            RecommendationListVo vo = new RecommendationListVo();
            BeanUtils.copyProperties(model, vo);
            if (StrUtil.isNotBlank(model.getCollegeCode()) && !codes.contains(model.getCollegeCode())) {
                codes.add(model.getCollegeCode());
            }
            vos.add(vo);
        });
        Map<String, College> map = refService.refCollege(codes);
        vos.forEach(vo -> {
            if (map.get(vo.getCollegeCode()) != null) {
                vo.setCollegeName(map.get(vo.getCollegeCode()).getName());
            }
        });
        return vos;
    }

    @Override
    public JsonResult read(Integer id) {
        if (id == null) {
            throw new ParameterException("参数对象为空");
        }

        DirectionalApplicationForm model = baseMapper.selectById(id);
        if (model == null) {
            throw new BusinessException("记录不存在");
        }
        DirectionalApplicationFormVO vo = new DirectionalApplicationFormVO();
        BeanUtils.copyProperties(model, vo);
        Student student = studentMapper.selectOne(new QueryWrapper<Student>().eq("user_id", model.getUserId()));
        if (student == null) {
            throw new ParameterException("学生信息异常");
        }
        vo.setXm(student.getXm());
        vo.setXh(student.getXh());
        vo.setXb(dictService.cacheLabel(DictConstants.TYPE_XB, student.getXb()));
        vo.setCsrq(student.getCsrq());
        vo.setMz(dictService.cacheLabel(DictConstants.TYPE_MZ, student.getMz()));
        vo.setZzmm(dictService.cacheLabel(DictConstants.TYPE_ZZMM, student.getZzmm()));
        vo.setSyszd(dictService.cacheLabel(DictConstants.TYPE_SYSZD, student.getSyszd()));
        vo.setMobile(student.getMobile());
        vo.setEmail(student.getEmail());
        College college = collegeMapper.selectOne(new QueryWrapper<College>().eq("code", student.getCollegeCode()));
        vo.setCollegeName(college.getName());
        Major major = majorMapper.selectOne(new QueryWrapper<Major>().eq("code", student.getMajorCode()));
        vo.setMajorName(major.getName());
        vo.setXl(dictService.cacheLabel(DictConstants.TYPE_XL, student.getXl()));
        return JsonResult.ok().setData(vo);
    }


    @Override
    public JsonResult read() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        User curUser = (User) authentication.getPrincipal();
        QueryWrapper<DirectionalApplicationForm> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", curUser.getUserId());
        DirectionalApplicationForm model = baseMapper.selectOne(wrapper);
        if (model == null) {
            DirectionalApplicationFormVO vo = new  DirectionalApplicationFormVO();
            Student student = studentMapper.selectOne(new QueryWrapper<Student>().eq("user_id", curUser.getUserId()));
            vo.setXm(student.getXm());
            vo.setXh(student.getXh());
            vo.setDegree(student.getDegree());
            vo.setXb(dictService.cacheLabel(DictConstants.TYPE_XB, student.getXb()));
            vo.setCsrq(student.getCsrq());
            vo.setMz(dictService.cacheLabel(DictConstants.TYPE_MZ, student.getMz()));
            vo.setZzmm(dictService.cacheLabel(DictConstants.TYPE_ZZMM, student.getZzmm()));
            vo.setSyszd(dictService.cacheLabel(DictConstants.TYPE_SYSZD, student.getSyszd()));
            vo.setMobile(student.getMobile());
            vo.setEmail(student.getEmail());
            College college = collegeMapper.selectOne(new QueryWrapper<College>().eq("code", student.getCollegeCode()));
            vo.setCollegeName(college.getName());
            Major major = majorMapper.selectOne(new QueryWrapper<Major>().eq("code", student.getMajorCode()));
            vo.setMajorName(major.getName());
            vo.setXl(dictService.cacheLabel(DictConstants.TYPE_XL, student.getXl()));
            return JsonResult.ok().setData(vo);
        }
        return read(model.getId());
    }


    @Override
    @Transactional
    public JsonResult add(DirectionalApplicationForm model) {
        if (model == null) {
            throw new ParameterException("参数对象为空");
        }
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        User curUser = (User) authentication.getPrincipal();
        QueryWrapper<DirectionalApplicationForm> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", curUser.getUserId());
        DirectionalApplicationForm tmp = baseMapper.selectOne(wrapper);
        model.setUserId(curUser.getUserId());
        model.setCollegeCode(curUser.getCollegeCode());
        Student student = studentMapper.selectOne(new QueryWrapper<Student>().eq("user_id", curUser.getUserId()));
        model.setXh(student.getXh());
        model.setXm(student.getXm());
        model.setDegree(student.getDegree());
        model.setUpdateTime(new Date());
        if(tmp == null){
            model.setStatus(RecommendationConstants.RECOMMENDATION_STATUS_INIT);
            model.setCreateTime(model.getUpdateTime());
            baseMapper.insert(model);
        }else {
            if(tmp.getStatus().equals(RecommendationConstants.RECOMMENDATION_STATUS_INIT)
                    || tmp.getStatus().equals(RecommendationConstants.RECOMMENDATION_STATUS_REJECT)){
                model.setId(tmp.getId());
                model.setCreateTime(tmp.getCreateTime());
                baseMapper.updateById(model);
            }else {
                return JsonResult.error("已有数据进入审核流程，请勿重复添加");
            }
        }
        return read(model.getId());
    }

    //    暂存
    @Override
    public JsonResult update(DirectionalApplicationForm model) {
        if (model == null) {
            throw new ParameterException("参数对象为空");
        }

        if (model.getId() == null) {
            throw new ParameterException("参数对象id为空");
        }
        DirectionalApplicationForm tmp = baseMapper.selectById(model.getId());
        if (tmp.getStatus().equals(RecommendationConstants.RECOMMENDATION_STATUS_INIT)
                || tmp.getStatus().equals(RecommendationConstants.RECOMMENDATION_STATUS_REJECT)) {
            model.setUpdateTime(new Date());
            baseMapper.updateById(model);
            return read(model.getId());
        }
        return JsonResult.error("当前审核状态不能修改");
    }

    //    提交
    @Override
    public JsonResult submit(Integer id) {
        if (id == null) {
            throw new ParameterException("参数对象id为空");
        }

        DirectionalApplicationForm model = baseMapper.selectById(id);
        if (model.getStatus().equals(RecommendationConstants.RECOMMENDATION_STATUS_INIT)
                || model.getStatus().equals(RecommendationConstants.RECOMMENDATION_STATUS_REJECT)) {
            model.setStatus(RecommendationConstants.RECOMMENDATION_STATUS_SUBMIT);
            model.setUpdateTime(new Date());
            baseMapper.updateById(model);
            return read(model.getId());
        }
        return JsonResult.error("已提交,请勿重复提交");
    }

    @Override
    public JsonResult delete(Integer[] ids) {
        if (ids == null) {
            throw new ParameterException("参数对象为空");
        }

        if (ids != null || ids.length > 0) {
            baseMapper.deleteBatchIds(Arrays.asList(ids));
        }
        return JsonResult.ok("删除成功");
    }

    //    审核
    @Override
    public JsonResult audit(RecommendationAuditParam param) {
        if (param == null) {
            throw new ParameterException("参数对象为空");
        }

        if (param.getId() == null) {
            throw new ParameterException("参数对象id为空");
        }

        DirectionalApplicationForm model = baseMapper.selectById(param.getId());
        if (!model.getStatus().equals(RecommendationConstants.RECOMMENDATION_STATUS_SUBMIT)) {
            throw new ParameterException("当前数据状态不满足审核条件");
        }
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        User curUser = (User) authentication.getPrincipal();
        model.setReviewUser(curUser.getUserId());
        model.setStatus(param.getStatus());
        model.setReviewComment(param.getComment());
        model.setReviewTime(new Date());
        baseMapper.updateById(model);

        return read(model.getId());
    }

//     导出
    @Override
    public JsonResult export(Integer id, HttpServletResponse response) throws IOException {
        DirectionalApplicationFormVO vo = (DirectionalApplicationFormVO) read(id).getData();
        String url = endpoint + "/" + MinioBucket.MINIO_RECMD + "/" + RecommendationConstants.Dir_App_Form + "/" + vo.getUserId() + ".pdf";
        String path = recmdDir + File.separator + RecommendationConstants.Dir_App_Form + File.separator + vo.getUserId() + ".pdf";
        if (!vo.getStatus().equals(RecommendationConstants.RECOMMENDATION_STATUS_PASS)) {
            return JsonResult.error("未通过审核，无法导出");
        }
        if (vo.getGenFlag().equals(RecommendationConstants.GEN_FLAG_NO)) {
            try {

                PdfWriter writer = new PdfWriter(new FileOutputStream(path));
                PdfDocument pdf = new PdfDocument(writer);
                Document document = new Document(pdf);
                addTableDocument(document, vo);
                document.close();
                writer.close();
                UpdateWrapper<DirectionalApplicationForm> wrapper = new UpdateWrapper<>();
                wrapper.eq("id", vo.getId()).set("gen_flag", RecommendationConstants.GEN_FLAG_YES)
                        .set("rpt_url", url);
                baseMapper.update(null, wrapper);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition",
                "attachment; filename=" + RecommendationConstants.Dir_App_Form + ".pdf");
        File file = new File(path);
        byte[] fileBytes = Files.readAllBytes(file.toPath());
        try (OutputStream os = response.getOutputStream()) {
            os.write(fileBytes);
        }
        return JsonResult.ok(url);
    }


    private void addTableDocument(Document document, DirectionalApplicationFormVO vo) {
        try {
            String fontUrl = pdfFont + "simsun.ttc,1";
            PdfFont font = PdfFontFactory.createFont(
                    fontUrl,
                    PdfEncodings.IDENTITY_H,                 // 编码
                    PdfFontFactory.EmbeddingStrategy.FORCE_EMBEDDED  // 嵌入策略
            );

            Paragraph title = new Paragraph("中南财经政法大学定向（非在职）毕业生网签申请表")
                    .setFont(font).setFontSize(18).setBold().setTextAlignment(TextAlignment.CENTER);
            document.add(title);

            Table table = new Table(new float[]{ 2f, 1f, 1f, 1f, 1f, 1f})
                    .setFont(font)
                    .setFontSize(13)
                    .setWidth(UnitValue.createPercentValue(100));


            table.addCell(createCell("姓名", font, true)).setTextAlignment(TextAlignment.CENTER);
            table.addCell(createCell(vo.getXm(), font, false));
            table.addCell(createCell("专业", font, true));
            table.addCell(createCell(vo.getMajorName(), font, false));
            table.addCell(createCell("学号", font, true));
            table.addCell(createCell(vo.getXh(), font, false));

            table.addCell(createCell("定向\n单位", font, true));
            table.addCell(new Cell(1, 5)
                    .setWidth(UnitValue.createPercentValue(10))
                    .add(new Paragraph(vo.getDirectionalWorkplace())));

            table.addCell(createCell("拟签\n单位", font, true));
            table.addCell(new Cell(1, 5)
                    .add(new Paragraph(vo.getProposedSigningWorkplace())));

            table.addCell(createCell("本\n人\n声\n明", font, true));
            table.addCell(new Cell(1, 5)
                    .add(new Paragraph()
                            .add("                                       \n")
                            .add("本人承诺：网签单位与上述拟签单位保持一致，否则愿承担由此产生的一切后果。\n").setTextAlignment(TextAlignment.LEFT)
                            .add(new Tab())
                            .addTabStops(new TabStop(250, TabAlignment.RIGHT))
                            .add("本人签名：\n") // 左对齐
                            .add(new Tab())
                            .addTabStops(new TabStop(450, TabAlignment.RIGHT))
                            .add("    年    月    日")) // 右对齐
                    .setPadding(5));

            table.addCell(createCell("学院\n意见", font, true));
            table.addCell(new Cell(1, 5)
                    .add(new Paragraph()
                            .add("                                       \n")
                            .add("                                       \n")
                            .add("                                       \n")
                            .add("辅导员意见："+ vo.getReviewComment()).setTextAlignment(TextAlignment.LEFT)
                            .add("                ")
                            .add("学院党委书记意见：\n")
                            .add(new Tab())
                            .addTabStops(new TabStop(400, TabAlignment.RIGHT))
                            .add("学院党委公章：\n")
                            .add(new Tab())
                            .addTabStops(new TabStop(300, TabAlignment.RIGHT))
                            .add("日      期："))
                    .setPadding(5));

            table.addCell(createCell("就业\n指导\n服务\n中心\n意见", font, true));
            Cell reviewCell = new Cell(1, 5)
                    .add(new Paragraph()
                            .add("                                       \n")
                            .add("                                       \n")
                            .add(vo.getReviewComment())
                            .add("                                       \n")
                            .add("                                       \n")
                            .add(new Paragraph()
                                    .add(new Tab())
                                    .addTabStops(new TabStop(300, TabAlignment.RIGHT))
                                    .add("负责人签名：（盖章）：\n")
                                    .add(new Tab())
                                    .addTabStops(new TabStop(350, TabAlignment.RIGHT))
                                    .add(formatDate(vo.getReviewTime()))
                            )
                    )
                    .setPadding(5);
            // 只有审核通过时添加签章
            if (vo.getStatus() == RECOMMENDATION_STATUS_PASS) {
                addSeal(reviewCell); // 调用签章方法
            }
            // 最后将单元格添加到表格
            table.addCell(reviewCell);

            table.addCell(createCell("备注", font, true));
            table.addCell(new Cell(1, 5)
                    .add(new Paragraph()
                            .add("依照《少数民族高层次骨干人才计划博士/硕士研究生（非在职考生）定向协议书》相关规定，毕业生在高校的学习结束后，必须回到定向省、自治区、直辖市、新疆生产建设兵团就业。\n").setBold().setTextAlignment(TextAlignment.LEFT)
                            .add("定向（非在职）毕业生网签须准备如下材料：\n").setBold()
                            .add("1、定向省内拟签约单位的接收函（原件或传真件）；\n").setBold()
                            .add("2、经学院审批的网签申请表（上表）\n").setBold()
                    .setPadding(5)));

            document.add(table);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 日期格式化方法（必须）
    private String formatDate(Date date) {
        if (date == null) return "   年   月   日";
        return new SimpleDateFormat("yyyy年MM月dd日").format(date);
    }

    // 辅助方法：创建标准单元格
    private Cell createCell(String text, PdfFont font, boolean isLabel) {
        return new Cell()
                .add(new Paragraph(text != null ? text : ""))
                .setFont(font)
                .setPadding(5)
                .setVerticalAlignment(VerticalAlignment.MIDDLE);
    }

    private void addSeal(Cell cell) {
        try{
            ImageData sealData = ImageDataFactory.create(pdfPicture + "careerGuidanceSeal.jpg");
            Image sealImage = new Image(sealData);

            BackgroundPosition backgroundPosition = new BackgroundPosition()
                    .setPositionX(BackgroundPosition.PositionX.RIGHT)
                    .setXShift(UnitValue.createPointValue(40))
                    .setPositionY(BackgroundPosition.PositionY.BOTTOM);
            BackgroundRepeat.BackgroundRepeatValue backgroundRepeatValue = BackgroundRepeat.BackgroundRepeatValue.NO_REPEAT;
            BackgroundRepeat backgroundRepeat = new BackgroundRepeat(backgroundRepeatValue, backgroundRepeatValue);
            BackgroundSize backgroundSize = new BackgroundSize();
            backgroundSize.setBackgroundSizeToValues(
                    UnitValue.createPointValue(Utilities.millimetersToPoints(35)),
                    UnitValue.createPointValue(Utilities.millimetersToPoints(35))
            );
            // 创建 BackgroundImage（关键修正）
            BackgroundImage backgroundImage = new BackgroundImage.Builder()
                    .setImage(sealImage.getXObject())  // 传递 Image 对象
                    .setBackgroundPosition(backgroundPosition)  // 图片居中
                    .setBackgroundRepeat(backgroundRepeat)  // 不重复平铺
                    .setBackgroundSize(backgroundSize)
                    .build();
            cell.setBackgroundImage(backgroundImage);
        } catch (IOException e) { e.printStackTrace(); }
    }

}